package com.sencorsta.ids.common.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.GeneratedMessageV3;
import com.sencorsta.ids.common.information.ErrorCodeList;
import com.sencorsta.ids.common.proto.PushKickMessage;
import com.sencorsta.ids.common.proto.utils.ReturnUtils;
import com.sencorsta.ids.core.application.master.MasterClient;
import com.sencorsta.ids.core.application.proxy.ProxyClient;
import com.sencorsta.ids.core.configure.TypeProtocol;
import com.sencorsta.ids.core.configure.TypeSerialize;
import com.sencorsta.ids.core.entity.ErrorMsg;
import com.sencorsta.ids.core.log.Out;
import com.sencorsta.ids.core.tcp.opensocket.OpenMessage;
import com.sencorsta.ids.core.tcp.opensocket.OpenServerBootstrap;
import com.sencorsta.ids.core.tcp.opensocket.OpenUser;
import com.sencorsta.ids.core.tcp.socket.protocol.RpcMessage;
import com.sencorsta.utils.date.DateUtil;
import com.sencorsta.utils.string.CodeUtil;
import com.sencorsta.utils.string.StringUtil;
import io.netty.channel.Channel;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.Random;

/**
 * @author TAO
 * @description: 将当前用户塞到channel
 * @date 2019/7/30 21:07
 */

public class LoginService implements RedisService {


    public static JSONObject login(String token, Channel channel) {

        JSONObject res = new JSONObject();
        if (token == null) {
            channel.closeFuture();
            res.put("msg", ErrorCodeList.TOKEN_FAILURE);
            return res;
        }

        try {
            JSONObject jsonToken = JSON.parseObject(CodeUtil.decode(token));//将token反向解析
            String userId = jsonToken.getString("userId");
            String phone = jsonToken.getString("phone");
            String UUID = jsonToken.getString("UUID");
            String proxyType = jsonToken.getString("proxyType");

            //是否是新用户标识
            Boolean sign=false;
            String currTime = DateUtil.getDateTime();
            if (!R_USER.exists(userId)) {//用户不存在
                sign=true;//新用户标识---盖个章---你是猪！！！
                String code="88888";
                String nickName=charNum();

                {
                    String sql="SELECT `code`,`nickName` FROM `randomNickNmae` LIMIT 0,1";
                    JSONArray jsz=MysqlServiceS.getInstance().select(sql);
                    if (jsz.size() > 0) {
                        JSONObject js = JSONObject.parseObject(String.valueOf(jsz.get(0)));
                        if (js.keySet().size() > 0) {
                            code=js.getString("code");
                            nickName=js.getString("nickName");
                        }
                    }
                }
                {
                    String sql="DELETE FROM `randomNickNmae` WHERE `code`="+code;
                    MysqlServiceS.getInstance().deleteAsyn(sql);
                }

                Random random = new Random();
                R_USER.hset(userId, "userId", userId);
                R_USER.hset(userId, "loginFirstTime", currTime);
                R_USER.hset(userId, "portrait", String.valueOf(random.nextInt(5) + 1));
                R_USER.hset(userId, "nickname", nickName);
                R_USER.hset(userId, "sex", "1");
                R_USER.hset(userId, "phone", phone);
                R_USER.hset(userId, "paypwd", "0");
                R_USER.hset(userId, "signature", "这个人什么都没留下");
                R_USER.hset(userId, "invitecode", code);
                R_USER.hset(userId, "type", String.valueOf(1));//1.普通用户  2.机器人

                Out.debug("------------------------------------------");

                Out.debug("------------------------------------------");

                //初始化钱包信息--开通钱包
                {
                    String sql = "INSERT INTO `wallet`(`userId`) VALUES(?)";
                    Object[] args = new Object[]{
                            userId
                    };
                    MysqlService.getInstance().insertAsyn(sql, args);
                }//修改登入状态
                {
                    String sql = "UPDATE `account` SET `status`=1 WHERE `UUID`=?";
                    Object[] args = new Object[]{
                            UUID
                    };
                    MysqlService.getInstance().updateAsyn(sql, args);
                }
            }


            R_USER.hset(userId, "loginLastTime", currTime);
            R_USER.hset(userId, "loginToken", token);
            InetSocketAddress insocket = (InetSocketAddress) channel.remoteAddress();
            R_USER.hset(userId, "IP", insocket.getAddress().getHostAddress());//1.普通用户  2.机器人

            //增加用户到组
            OpenUser user = new OpenUser();
            user.userId = userId;
            user.channel = channel;
            user.channel.attr(OpenServerBootstrap.getInstance().KEY_OPENUSER).set(user);

            OpenUser oldChannel = OpenServerBootstrap.getInstance().users.put(userId, user);

            if (oldChannel == null) {
                String SID = R_ROUTE.hget(userId, proxyType);
                if (!StringUtil.isEmpty(SID)) {
                    JSONObject rpcJson = new JSONObject();
                    rpcJson.put("userId", userId);
                    RpcMessage rpcMessage = new RpcMessage();
                    rpcMessage.header.type = TypeProtocol.TYPE_RPC_REQ;
                    rpcMessage.method = "kick";
                    rpcMessage.serializeType = TypeSerialize.TYPE_JSON;
                    rpcMessage.data = rpcJson.toJSONString().getBytes(Charset.forName("UTF-8"));
                    rpcMessage.userId = userId;
                    ProxyClient.sendBySID(rpcMessage, proxyType, SID);
                }

            } else {
                PushKickMessage.PushKick.Builder push = PushKickMessage.PushKick.newBuilder();
                push.setMsg(ReturnUtils.ErrorProto(ErrorCodeList.KICKOFF));
                OpenMessage message = new OpenMessage();
                message.method = "push.Kick";
                message.serializeType = TypeSerialize.TYPE_PROTOBUF;
                message.data = protpToByte(push);
                message.header.type = TypeProtocol.TYPE_RES;
                message.channel = oldChannel.channel;
                //OpenServerBootstrap.getInstance().addMessage(message);//sendMessage(message);
                oldChannel.channel.writeAndFlush(message);
                oldChannel.channel.attr(OpenServerBootstrap.getInstance().KEY_OPENUSER).set(null);
                oldChannel.channel.closeFuture();

            }


            R_ROUTE.hset(userId, proxyType, MasterClient.getInstance().localServer.sid);//将当前连接的proxy服务器的sid添加带用户路由

            res.put("msg", new ErrorMsg());
            res.put("userId", userId);

            //TODO mySql持久化
            if (sign){//sign是true为新用户----那么这只猪就进来----并且送到mysql的屠宰场杀掉
                Out.debug("------------------------新用户数据持久化-----------------------------");
                //通过userId得到redis的数据
                Map<String,String> userInfo=R_USER.hgetAll(userId);
                String sql="INSERT INTO `userInfo` (`userId`,`nickname`,`sex`,`type`,`portrait`,`invitecode`,`loginFirstTime`,`loginLastTime`) VALUES(?,?,?,?,?,?,?,?)";
                Object[] args=new Object[]{
                        userInfo.get("userId"),userInfo.get("nickname"),userInfo.get("sex"),userInfo.get("type"),userInfo.get("portrait"),userInfo.get("invitecode"),userInfo.get("loginFirstTime"),userInfo.get("loginLastTime")
                };
                try {
                   MysqlService.getInstance().insertAsyn(sql,args);
                }catch (Exception e){
                    Out.error("新用户信息持久化失败，错误接口：LoginService  当前用户id为"+userId+"需要手动导入");
                }
            }else{//老用户更新token+currTime
                Out.debug("------------------------老用户更新-----------------------------");
                String sql="update `userInfo` set loginLastTime=? where userId=?";
                Object[] args=new Object[]{
                        currTime,userId
                };
                try {
                    MysqlService.getInstance().updateAsyn(sql,args);
                }catch (Exception e){
                    Out.error("老用户信息更新失败，错误接口：LoginService  当前用户id为"+userId+"需要手动导入");
                }
            }

            return res;
        } catch (IOException e) {
            res.put("msg", ErrorCodeList.SERVER_ERROR);
            return res;
        }


    }

    //产生数字 + 字母随机组合
    public static String charNum() {
        String val = "";
        Random random = new Random();
        for (int i = 0; i < 5; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            if ("char".equalsIgnoreCase(charOrNum)) {
                int choice = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char) (choice + random.nextInt(26));
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    public static byte[] protpToByte(GeneratedMessageV3.Builder res) {
        ByteArrayOutputStream output = new ByteArrayOutputStream();

        try {
            res.build().writeTo(output);
        } catch (IOException var4) {
            var4.printStackTrace();
        }

        byte[] byteArray = output.toByteArray();
        return byteArray;
    }


}
